set_policy("build.warning", true)

target("bmalloc")
  set_kind("static")
  add_files(
    "Source/bmalloc/bmalloc/*.cpp|Zone.cpp", 
    "Source/bmalloc/libpas/src/libpas/*.c")
  if is_plat("macosx") then
    add_includedirs("Source/bmalloc/bmalloc/darwin", {public = true})
    add_files("Source/bmalloc/bmalloc/Zone.cpp")
  elseif is_plat("windows") then
    add_cflags("/wd4206")
  end
  remove_files("Source/bmalloc/libpas/src/test/*.cpp")
  add_includedirs(
     "Source/bmalloc/libpas/src",
    "Source/bmalloc/libpas/src/libpas",
    "Source/bmalloc/bmalloc",
    {public = true})
  add_defines("_GNU_SOURCE", "PAS_BMALLOC=1")
  set_languages("c++20") -- bit_cast
  after_build(function(target) 
    os.mkdir("Source/bmalloc/headers/bmalloc")
    os.cp("Source/bmalloc/libpas/src/*.h", "Source/bmalloc/headers/bmalloc")
    os.cp("Source/bmalloc/libpas/src/libpas/*.h", "Source/bmalloc/headers/bmalloc")
    os.cp("Source/bmalloc/*.h", "Source/bmalloc/headers/bmalloc")
  end)


target("WTF")
  set_kind("static")
  add_files(
    "Source/WTF/wtf/*.cpp", 
    "Source/WTF/wtf/dragonbox/*.cpp", 
    "Source/WTF/wtf/dtoa/*.cc", 
    "Source/WTF/wtf/persistence/*.cpp",
    "Source/WTF/wtf/text/*.cpp", 
    "Source/WTF/wtf/text/icu/*.cpp", 
    "Source/WTF/wtf/threads/*.cpp", 
    "Source/WTF/wtf/dragonbox/dragonbox_to_chars.cpp",
    "Source/WTF/wtf/unicode/**/*.cpp",
    "Source/WTF/wtf/generic/WorkQueueGeneric.cpp",
    "Source/WTF/wtf/generic/MainThreadGeneric.cpp",
    "Source/WTF/wtf/posix/OSAllocatorPOSIX.cpp",
    "Source/WTF/wtf/posix/ThreadingPOSIX.cpp",
    "Source/WTF/wtf/posix/CPUTimePOSIX.cpp",
    "Source/WTF/wtf/posix/FileSystemPOSIX.cpp",
    "Source/WTF/wtf/text/unix/TextBreakIteratorInternalICUUnix.cpp",
    "Source/WTF/wtf/unix/LanguageUnix.cpp",
    "Source/WTF/wtf/unix/LoggingUnix.cpp",
    "Source/WTF/wtf/unix/UniStdExtrasUnix.cpp"

    )
  remove_files(
    "Source/WTF/benchmarks/*.cpp", 
    "Source/WTF/wtf/playstation/*.cpp")
  add_includedirs(
    "Source/WTF", 
    "Source/WTF/icu",
    "Source/WTF/wtf",
    "Source/bmalloc", 
    "Source/bmalloc/bmalloc", 
    "Source/WTF/wtf/dtoa",
    "Source/WTF/wtf/fast_float", 
    "Source/WTF/wtf/persistence", 
    "Source/WTF/wtf/simdutf", 
    "Source/WTF/wtf/text",
    "Source/WTF/wtf/text/icu", 
    "Source/WTF/wtf/threads", 
    "Source/WTF/wtf/unicode",
    {public = true})
  add_defines("ENABLE_WEBASSEMBLY=0", "ENABLE_FTL_JIT=0")
  if is_plat("macosx") then
      add_frameworks("Cocoa", "CoreFoundation", "Security")
      add_defines("WTF_DEFAULT_EVENT_LOOP=0")
      add_links("readline")
      add_files(
          -- "Source/WTF/wtf/cocoa/*.cpp", 
          -- "Source/WTF/wtf/cocoa/*.mm", 
          "Source/WTF/wtf/darwin/OSLogPrintStream.mm",
          "Source/WTF/wtf/cocoa/MemoryFootprintCocoa.cpp",
          "Source/WTF/wtf/generic/MemoryPressureHandlerGeneric.cpp"
          -- "Source/WTF/wtf/mac/*.mm", 
          -- "Source/WTF/wtf/posix/*.cpp", 
          -- "Source/WTF/wtf/text/cocoa/*.cpp", 
          -- "Source/WTF/wtf/text/cocoa/*.mm", 
          -- "Source/WTF/wtf/BlockObjCExceptions.mm",
          -- "Source/WTF/wtf/ObjCRuntimeExtras.mm",
          -- "Source/WTF/wtf/ProcessPrivilege.cpp",
          -- "Source/WTF/wtf/TranslatedProcess.cpp",
          -- "Source/WTF/wtf/darwin/OSLogPrintStream.mm", 
          -- "Source/WTF/wtf/cf/*.cpp",
          -- "Source/WTF/wtf/generic/*.cpp"
          )
      add_includedirs(
          "Source/WTF/wtf/cf", 
          "Source/WTF/wtf/cocoa", 
          "Source/WTF/wtf/darwin", 
          "Source/WTF/wtf/spi/cf",
          "Source/WTF/wtf/spi/cocoa", 
          "Source/WTF/wtf/spi/darwin", 
          "Source/WTF/wtf/spi/mac", 
          "Source/WTF/wtf/text/cf",
          {public = true})
      -- MachExceptions.def generate
      add_files(
        "$(buildir)/derived_sources/mach_excServer.c", 
        "$(buildir)/derived_sources/mach_excUser.c")
      add_includedirs("$(buildir)/derived_sources")
      before_build(function (target) 
        os.cp("Source/WTF/wtf/mac/MachExceptions.defs", "$(buildir)/derived_sources/")
        -- failed(255)
        -- os.execv("mig", {
        --     "-DMACH_EXC_SERVER_TASKIDTOKEN_STATE",
        --     "-v",
        --     "$(buildir)/derived_sources/MachExceptions.defs"
        -- }, {curdir = "$(buildir)/derived_sources"})
      end)
  elseif is_plat("windows") then
    add_files(
      "Source/WTF/wtf/text/win/*.cpp", 
      "Source/WTF/wtf/win/*.cpp"
      )
    -- remove_files(
    --   "Source/WTF/wtf/win/MemoryFootprintWin.cpp", 
    --   "Source/WTF/wtf/win/MemoryPressureHandlerWin.cpp"
    --   )
    add_includedirs(
        "Source/WTF/wtf/win", 
        "Source/WTF/wtf/text/win",
        {public = true})
  elseif is_plat("linux") then
    add_includedirs("Source/WTF/wtf/linux", 
      "Source/WTF/wtf/text/linux",
      {public = true})
    add_files(
      -- "Source/WTF/wtf/glib/*.cpp",
      -- "Source/WTF/wtf/posix/*.cpp",
      "Source/WTF/wtf/unix/MemoryPressureHandlerUnix.cpp",
      "Source/WTF/wtf/generic/MemoryFootprintGeneric.cpp"
      )
  elseif is_plat("iphoneos") then
    add_files("Source/WTF/wtf/ios/*.cpp")
  elseif is_plat("wasm") then
    add_defines("ENABLE_WEBASSEMBLY=1")
  else 
    add_files(
      "Source/WTF/wtf/generic/MemoryFootprintGeneric.cpp",
      "Source/WTF/wtf/generic/MemoryPressureHandlerGeneric.cpp"
    )
  end
  set_languages("c++20")
  add_deps("bmalloc", "icu")

target("icu")
  set_kind("static")
  set_languages("c++17")
  add_files(
    "Source/icu/icu4c/source/common/*.cpp",
    "Source/icu/icu4c/source/i18n/*.cpp"
    )
  add_includedirs(
    "Source/icu/icu4c/source/", 
    "Source/icu/icu4c/source/common/", 
    "Source/icu/icu4c/source/i18n",
    "Source/icu/icu4c/source/io",
    "Source/icu/icu4c/source/layoutex",
    "Source/icu/icu4c/source/tools/toolutil",
    {public = true})
  add_defines(
    "U_STATIC_IMPLEMENTATION", 
    "U_COMMON_IMPLEMENTATION",
    "U_I18N_IMPLEMENTATION"
    -- "U_I18N_IMPLEMENTATION", 
    -- "U_ATTRIBUTE_DEPRECATED",
    -- "HAVE_DLFCN_H=0", 
    -- "HAVE_DLOPEN=0", 
    -- "U_NOEXCEPT", 
    -- "U_USING_ICU_NAMESPACE=0", 
    -- "U_ENABLE_DYLOAD=0", 
    -- "ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC",
    -- "U_DISABLE_VERSION_SUFFIX=1",
    -- "U_SHOW_CPLUSPLUS_API=0",
    -- "U_ICU_ENTRY_POINT_RENAME=1"
    )

  if is_plat("android") then 
    add_cxflags("-std=c++17")
    add_syslinks("log")
  elseif is_plat("linux") then
    add_cxflags("-std=c++17")
    add_syslinks("pthread", "dl")
  elseif is_plat("macosx") then
    add_cxflags("-std=c++17", "-stdlib=libc++")
    add_cflags("/wd4005", "/wd4068", "/wd4267", "/utf-8")
  elseif is_plat("android") then
    add_cxflags("-std=c++17", "-stdlib=libc++")
  elseif is_plat("windows") then
    add_defines("WIN32_LEAN_AND_MEAN", "_CRT_SECURE_NO_WARNINGS")
    add_syslinks("ws2_32")
    add_defines("UCHAR_TYPE=wchar_t", "WIN32", "_WINDOWS")
  elseif is_plat("wasm") then
    add_cxflags("-std=c++17")
  end
  on_install(function (target)
      os.cp("$(projectdir)/icu4c/source/common/*.h", path.join(target:installdir(), "include/common"))
      os.cp("$(projectdir)/icu4c/source/i18n/*.h", path.join(target:installdir(), "include/i18n"))
      os.cp("$(target:targetfile())", path.join(target:installdir(), "lib"))
  end)




target("JavaScriptCore")
  set_kind("shared")
  add_files(
    "Source/JavaScriptCore/API/*.cpp",
    -- "Source/JavaScriptCore/assembler/*.cpp",
    "Source/JavaScriptCore/b3/air/*.cpp",
    "Source/JavaScriptCore/b3/*.cpp",
    "Source/JavaScriptCore/builtins/*.cpp",
    "Source/JavaScriptCore/bytecode/*.cpp",
    "Source/JavaScriptCore/bytecompiler/*.cpp",
    "Source/JavaScriptCore/debugger/*.cpp",
    "Source/JavaScriptCore/dfg/*.cpp",
    "Source/JavaScriptCore/disassembler/CapstoneDisassembler.cpp",
    "Source/JavaScriptCore/disassembler/Disassembler.cpp",
    "Source/JavaScriptCore/disassembler/zydis/Zydis/*.c",
    -- "Source/JavaScriptCore/domjit/*.cpp",
    "Source/JavaScriptCore/ftl/*.cpp",
    "Source/JavaScriptCore/heap/*.cpp",
    -- "Source/JavaScriptCore/inspector/*.cpp",
    -- "Source/JavaScriptCore/inspector/agents/*.cpp",
    "Source/JavaScriptCore/interpreter/*.cpp",
    -- "Source/JavaScriptCore/jit/*.cpp",
    -- "Source/JavaScriptCore/llint/*.cpp",
    "Source/JavaScriptCore/parser/*.cpp"
    -- "Source/JavaScriptCore/profiler/*.cpp",
    -- "Source/JavaScriptCore/runtime/*.cpp",
    -- "Source/JavaScriptCore/tools/*.cpp",
    -- "Source/JavaScriptCore/yarr/*.cpp"
    )
  add_includedirs(
    "Source/JavaScriptCore",
    "Source/JavaScriptCore/API",
    "Source/JavaScriptCore/assembler",
    "Source/JavaScriptCore/b3",
    "Source/JavaScriptCore/b3/air",
    "Source/JavaScriptCore/builtins",
    "Source/JavaScriptCore/bytecode",
    "Source/JavaScriptCore/bytecompiler",
    "Source/JavaScriptCore/debugger",
    "Source/JavaScriptCore/dfg",
    "Source/JavaScriptCore/disassembler",
    "Source/JavaScriptCore/disassembler/zydis",
    "Source/JavaScriptCore/disassembler/zydis/Zydis",
    "Source/JavaScriptCore/domjit",
    "Source/JavaScriptCore/ftl",
    "Source/JavaScriptCore/heap",
    "Source/JavaScriptCore/inspector",
    "Source/JavaScriptCore/interpreter",
    "Source/JavaScriptCore/inspector/agents",
    "Source/JavaScriptCore/jit",
    "Source/JavaScriptCore/llint",
    "Source/JavaScriptCore/parser",
    "Source/JavaScriptCore/profiler",
    "Source/JavaScriptCore/runtime",
    "Source/JavaScriptCore/tools",
    "Source/JavaScriptCore/yarr",
    "Source/JavaScriptCore/wasm",
    "Source/JavaScriptCore/inspector/remote",
    "Source/bmalloc/headers"
    )
    remove_files(
      "Source/JavaScriptCore/API/JSRemoteInspector.cpp",
      "Source/JavaScriptCore/API/*Private.cpp",
      "Source/JavaScriptCore/API/*Internal.cpp",
      "Source/JavaScriptCore/API/JSStringRefBSTR.cpp",
      "Source/JavaScriptCore/b3/test*.cpp"
      )
    remove_headerfiles(
      "Source/JavaScriptCore/API/JSContextInternal.h",
      "Source/JavaScriptCore/API/*Private.h",
      "Source/JavaScriptCore/API/*Internal.h",
      "Source/JavaScriptCore/API/JSStringRefBSTR.h"
      )
    add_defines("ENABLE_REMOTE_INSPECTOR=0", "ENABLE_INSPECTOR_ALTERNATE_DISPATCHERS=0", "JSC_OBJC_API_ENABLED=0","ENABLE_FTL_JIT=0", "ENABLE_WEBASSEMBLY=0")
  if is_arch("x86", "x86_64", "i386") then
    add_files("Source/JavaScriptCore/disassembler/X86Disassembler.cpp")
  elseif is_arch("armeabi-v7a", "armeabi", "armv7-a", "armv5te", "arm64-v8a") then
    add_files("Source/JavaScriptCore/disassembler/ARM64Disassembler.cpp")
    add_files("Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp")
  elseif is_arch("riscv", "riscv64") then
    add_files("Source/JavaScriptCore/disassembler/RISCV64Disassembler")
  end

  if is_plat("wasm")then
    add_files("Source/JavaScriptCore/wasm/*.cpp")
    add_files("Source/JavaScriptCore/wasm/js/*.cpp")
    add_defines("ENABLE_WEBASSEMBLY=1")
  elseif is_plat("macosx") then
    -- add_files("Source/JavaScriptCore/API/*.mm")
    add_files("Source/JavaScriptCore/API/PASReportCrashPrivate.cpp")
  elseif is_plat("windows") then
    add_headerfiles("Source/JavaScriptCore/API/JSStringRefBSTR.h")
    add_files("Source/JavaScriptCore/API/JSStringRefBSTR.cpp")
  end
  before_build(function(target) 
    local derived_dir = path.join(target:scriptdir(), "Source/JavaScriptCore/derrivedSources")
    local outputs = {
          path.join(derived_dir, "Bytecodes.h"),
          path.join(derived_dir, "InitBytecodes.asm"),
          path.join(derived_dir, "BytecodeStructs.h"),
          path.join(derived_dir, "BytecodeIndices.h"),
          path.join(derived_dir, "WasmLLIntGeneratorInlines.h"),
          path.join(derived_dir, "InitWasm.asm"),
          path.join(derived_dir, "BytecodeDumperGenerated.cpp"),
          path.join(derived_dir, "JSCBuiltins.cpp"),
          path.join(derived_dir, "JSCBuiltins.h"),
          path.join(derived_dir, "KeywordLookup.h")
      }
    local bytecode_args = {
        "--bytecodes_h", outputs[1],
        "--init_bytecodes_asm", outputs[2],
        "--bytecode_structs_h", outputs[3],
        "--bytecode_indices_h", outputs[4],
        path.join(target:scriptdir(), "Source/JavaScriptCore/bytecode/BytecodeList.rb"),
        "--wasm_json", path.join(target:scriptdir(), "Source/JavaScriptCore/wasm/wasm.json"),
        "--wasm_llint_generator_h", outputs[5],
        "--init_wasm_llint", outputs[6],
        "--bytecode_dumper", outputs[7]
    }
    os.mkdir(derived_dir)
    os.execv("ruby", table.join(path.join(target:scriptdir(), "Source/JavaScriptCore/generator/main.rb"), bytecode_args))
    -- target:add("files",outputs[2], outputs[7])
    if is_plat("emscripten") then
      target:add("files", outputs[6])
    end
    target:add("includedirs", derived_dir)
    -- builtin js 
    local JavaScriptCore_BUILTINS_SOURCES = os.files("Source/JavaScriptCore/builtins/*.js")
    local builtin_args = {
                  "--framework", "JavaScriptCore",
                  "--output-directory", derived_dir,
                  "--combined"
    }
    table.join2(builtin_args, JavaScriptCore_BUILTINS_SOURCES)
    os.execv("python3", table.join(path.join(target:scriptdir(), "Source/JavaScriptCore/Scripts/generate-js-builtins.py"), builtin_args))
    target:add("files", outputs[8])
    -- aircode
    os.execv("ruby", table.join( 
      path.join(target:scriptdir(), "Source/JavaScriptCore/b3/air/opcode_generator.rb"),
      path.join(target:scriptdir(), "Source/JavaScriptCore/b3/air/AirOpcode.opcodes")
    ))
    -- keyworklookup
    os.execv("python3", table.join(
      path.join(target:scriptdir(), "Source/JavaScriptCore/KeywordLookupGenerator.py"),
      path.join(target:scriptdir(), "Source/JavaScriptCore/parser/Keywords.table"),
      ">",
      outputs[9]
    ))
  end)
  add_deps("WTF", "icu", "bmalloc")
  set_languages("c++20")